<?php

require_once __DIR__ . '/../src/Enums/FrameType.php';
require_once __DIR__ . '/../src/Enums/ReasonCode.php';
require_once __DIR__ . '/../src/Enums/DeviceFlag.php';
require_once __DIR__ . '/../src/Enums/ChannelType.php';
require_once __DIR__ . '/../src/FrameInterface.php';
require_once __DIR__ . '/../src/Framer.php';
require_once __DIR__ . '/../src/Decoder.php';
require_once __DIR__ . '/../src/Encoder.php';
require_once __DIR__ . '/../src/Protocol.php';
require_once __DIR__ . '/../src/Packets/PingPacket.php';
require_once __DIR__ . '/../src/Packets/PongPacket.php';
require_once __DIR__ . '/../src/Packets/ConnectPacket.php';

use Dongasai\WkProtoPhp\Protocol;
use Dongasai\WkProtoPhp\Packets\ConnectPacket;
use Dongasai\WkProtoPhp\Packets\PingPacket;
use Dongasai\WkProtoPhp\Enums\DeviceFlag;

echo "WkProtoPHP 使用示例\n";
echo "==================\n\n";

// 1. 创建协议解析器
$protocol = new Protocol();

// 2. 创建和发送CONNECT包
echo "1. 创建CONNECT连接包\n";
$connectPacket = new ConnectPacket();
$connectPacket->setVersion(5);
$connectPacket->setUid('user_123456');
$connectPacket->setToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9');
$connectPacket->setDeviceId('iphone_13_pro');
$connectPacket->setDeviceFlag(DeviceFlag::ANDROID->value);
$connectPacket->setClientTimestamp(time() * 1000); // 毫秒时间戳
$connectPacket->setClientKey('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA');

echo "CONNECT包信息: " . $connectPacket . "\n";

// 3. 编码CONNECT包
echo "\n2. 编码CONNECT包\n";
try {
    $encodedData = $protocol->encodeFrame($connectPacket);
    echo "编码成功! 数据长度: " . strlen($encodedData) . " 字节\n";
    echo "十六进制数据: " . bin2hex($encodedData) . "\n";
} catch (\Exception $e) {
    echo "编码失败: " . $e->getMessage() . "\n";
}

// 4. 解码CONNECT包
echo "\n3. 解码CONNECT包\n";
try {
    [$decodedPacket, $length, $error] = $protocol->decodeFrame($encodedData);
    if ($error) {
        echo "解码失败: " . $error->getMessage() . "\n";
    } else {
        echo "解码成功!\n";
        echo "解码后的包: " . $decodedPacket . "\n";
        echo "消耗字节数: " . $length . "\n";
    }
} catch (\Exception $e) {
    echo "解码异常: " . $e->getMessage() . "\n";
}

// 5. 处理心跳包
echo "\n4. 处理心跳包\n";

// 创建PING包
$pingPacket = new PingPacket();
$pingData = $protocol->encodeFrame($pingPacket);
echo "PING包编码成功，长度: " . strlen($pingData) . " 字节\n";

// 模拟服务器返回PONG包
[$decodedPing, $pingLength] = $protocol->decodeFrame($pingData);
echo "收到PING包: " . $decodedPing . "\n";

$pongPacket = new Dongasai\WkProtoPhp\Packets\PongPacket();
$pongData = $protocol->encodeFrame($pongPacket);
echo "返回PONG包，长度: " . strlen($pongData) . " 字节\n";

// 6. 网络通信示例
echo "\n5. 网络通信示例\n";
echo "在实际应用中，你可以这样使用:\n";
echo <<<CODE
// 客户端发送数据
\$socket = fsockopen('tcp://localhost:8080', \$errno, \$errstr, 30);
if (\$socket) {
    // 发送CONNECT包
    fwrite(\$socket, \$encodedData);
    
    // 接收服务器响应
    \$response = fread(\$socket, 1024);
    [\$responsePacket, \$length, \$error] = \$protocol->decodeFrame(\$response);
    
    // 处理响应...
    fclose(\$socket);
}

// 服务器端处理
while (true) {
    \$data = fread(\$clientSocket, 1024);
    if (strlen(\$data) === 0) break;
    
    [\$packet, \$length, \$error] = \$protocol->decodeFrame(\$data);
    if (\$packet) {
        // 根据包类型处理
        switch (\$packet->getFrameType()) {
            case FrameType::CONNECT:
                // 处理连接
                break;
            case FrameType::PING:
                // 返回PONG
                \$pong = new PongPacket();
                fwrite(\$clientSocket, \$protocol->encodeFrame(\$pong));
                break;
            // 其他包类型...
        }
    }
}
CODE;

echo "\n\n6. 错误处理示例\n";
echo "协议解析器提供了完整的错误处理机制:\n";

// 测试不完整的数据
$incompleteData = substr($encodedData, 0, 10);
[, , $error] = $protocol->decodeFrame($incompleteData);
if ($error) {
    echo "不完整数据错误: " . $error->getMessage() . "\n";
}

// 测试无效的数据
$invalidData = "\xFF\xFF\xFF\xFF";
[, , $error] = $protocol->decodeFrame($invalidData);
if ($error) {
    echo "无效数据错误: " . $error->getMessage() . "\n";
}

echo "\n示例完成!\n";